JS - Promises
Inleiding
Promises zijn er niet om callbacks te vervangen. Promises bieden een betrouwbare tussenpersoon (proxy) tussen de de code die de promise aanroept en de asynchrone code die de taak in de toekomst zal uitvoeren om callbacks te beheren.
Promises kunnen aan elkaar worden geketend (chained), waarmee een reeks van asychronoon te voltooien stappen gepland kan worden.
Een Promise is een belofte, het is een toekomstige waarde, een time-onafhankelijke container die rond een waarde wordt gewikkeld. Je moet over deze container op identieke wijze nadenken los van de vraag of de onderliggende waarde definitief is of niet. Het observeren van de vervulling van een promise haalt de deze waarde op zodra ze beschikbaar is. Met andere woorden, van een Promise wordt gezegd dat ze de asynchrone versie is van een sync functie's return waarde.
Een Promise kan slechts één van de twee mogelijke resolutie uitkomsten hebben:
- vervuld of
- afgewezen, met een optionele enkele waarde.
Als een Promise wordt nagekomen, wordt eindwaarde een vervulling (fullfillment) genoemd. Als de Promise wordt afgewezen, wordt de uiteindelijke waarde een reden (reason) genoemd (zoals bij een "reden voor afwijzing"). Promises kunnen slechts eenmalig opgelost worden (vervulling of afwijzing). Elke verdere poging om de Promise te vervullen of af te wijzen wordt genegeerd. Dat wil zeggen dat eens een Promise opgelost is, het een onveranderlijke waarde is die niet meer kan worden gewijzigd.
Het is duidelijk dat er verschillende manieren zijn om na te denken over wat een Promise is. Geen enkel perspectief volstaat. Maar Promises zijn in elk geval een aanzienlijke verbetering ten opzichte van callbacks-only async, namelijk ze bieden orde, voorspelbaarheid en betrouwbaarheid.
Een Promise maken en gebruiken
Om een instantie van een Promise
te maken gebruikt je de Promise()
constructor:
var p = new Promise( function(resolve,reject){ // .. } );
De twee opgegeven parameters in de Promise()
constructor zijn functies en worden meestal resolve()
en reject()
genoemd. Ze worden als volgt gebruikt:
- Als je
reject()
oproept wordt de Promise afgewezen. Als je een argument meegeeft is dat de reden waarvoor de Promise wordt afgewezen. - Als je
resolve()
oproept zonder argument is de belofte vervuld. - Als je
resolve()
oproept en je geeft een andere Promise mee als argument, neemt deze laatste Promise de state (toestand) van de eerste Promise over, namelijk vervuld of afgewezen.
Hier volgt een eenvoudig voorbeeld. De variabele done
staat ingesteld op false
. Normaal gezien zet je hier code die een toekomstige handeling evalueert. Verander de waarde van done
en stel die in op true
.
<!-- JavaScript Promises There and back again By Jake Archibald Published: December 16th, 2013 Updated: September 26th, 2016 http://www.html5rocks.com/en/tutorials/es6/promises/ --> <!doctype html> <html lang="nl"> <head> <meta charset="UTF-8"> <title>Promises</title> <script> /* JavaScript Promises There and back again By Jake Archibald Published: December 16th, 2013 Updated: September 26th, 2016 http://www.html5rocks.com/en/tutorials/es6/promises/ */ var alsHetWerkt = new Promise(function(resolve, reject) { // do a thing, possibly async, then… var done = false; /* everything turned out fine */ if (done) { resolve("Het werkt!"); } else { reject(Error("Het werkt niet...")); } }); alsHetWerkt.then( function(result) { /* als het werkt doe dit */ console.log(result); // "Het werkt!" }, function(err) { /* anders doe dat */ console.log(err.message, err.name); // "Het werkt niet..." } ); </script> </head> <body> </body> </html>
In het voorbeeld hierboven maken gebruik van het JavaScript Error Object. Meer info op MDN, Error.
then
Alle instanties van Promise
beschikken over een then methode waarmee je kan reageren om het vervullen of afwijzen van de 'belofte'. De eerste then
callback methode krijgt als argument de retourwaarde van de resolve()
methode mee:
var p = new Promise(function(resolve, reject) { // A mock async action using setTimeout setTimeout(function() { resolve('er zijn 2 seconden verlopen'); }, 2000); }); p.then(function(result) { console.log(result); });
De then
callback wordt afgevuurd als de belofte vervuld is.
Je kan de then
methode aaneenschakelen:
var p2 = new Promise(function(resolve, reject) { // A mock async action using setTimeout setTimeout(function() { resolve('er zijn 4 seconden verlopen'); }, 4000); }); p2.then(function(result) { console.log('then 1:', result); return 'na 4 sec belofte vervuld, bewerkt en doorgegeven 2de then'; }).then(function(result) { console.log('then 2', result); return 'resultaat van 1ste then door 2de then bewerkt en doorgegeven'; }).then (function(result) { console.log('then 3', result);});
Elke then
methode krijgt de retourwaarde van de vorige then
mee. Als een belofte vervuld is en then
wordt opnieuw opgeroepen wordt de callback onmiddellijk uitgevoerd. Als de belofte afgewezen wordt en je roep then
op na de afwijzing wordt de callback nooit uitgevoerd.
catch
De catch callback methode wordt uitgevoerd als de promise verworpen wordt. Wat je meegeeft bepaal je zef. Een veel voorkomend patroon is het gebruik van het JavaScript Error
Object. Meer info op MDN, Error.
HTML
<h1>Promises: de <code>catch</code> methode</h1> <p style="color: red">Open het Console venster (links onder) om met deze Pen te werken!</p> <div> <p>klik binnen de 5 seconden op akkood!!!</p> <input type=checkbox id="akkoord"/> <label for="akkoord">akkoord </label> </div>
JS
var p = new Promise(function(resolve, reject) { // A mock async action using setTimeout setTimeout(function() { var akkoord = document.getElementById('akkoord').checked; if (akkoord) { resolve('Je hebt tijdig onze voorwaarden aanvaard!'); } else { reject(Error('Je hebt niet tijdig onze voorwaarden aanvaard!')); } }, 5000); }); p.then(function(result) { console.log(result); }).catch(function(result) { console.log(result.message); });
Bronnen
- Kyle Simpson, You Don’t Know JS: ES6 & Beyond, O’Reilly, 2016
- David Walsh, JavaScript Promise API, november 2, 2015
- Jecelyn Yeen, JavaScript Promises for Dummies, Get to know JavaScript Promises better, Dec 01, 2016
- JavaScript Kit, Beginner's Guide to JavaScript promises, Sept 21st, 2015